package com.Sony.TemplateGame;

import java.util.Vector;

import org.anddev.andengine.engine.Engine;
import org.anddev.andengine.engine.camera.BoundCamera;
import org.anddev.andengine.engine.camera.hud.HUD;
import org.anddev.andengine.engine.handler.IUpdateHandler;
import org.anddev.andengine.engine.options.EngineOptions;
import org.anddev.andengine.engine.options.EngineOptions.ScreenOrientation;
import org.anddev.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.anddev.andengine.entity.layer.tiled.tmx.TMXLoader;
import org.anddev.andengine.entity.layer.tiled.tmx.TMXObject;
import org.anddev.andengine.entity.layer.tiled.tmx.TMXObjectGroup;
import org.anddev.andengine.entity.layer.tiled.tmx.TMXTiledMap;
import org.anddev.andengine.entity.layer.tiled.tmx.util.exception.TMXLoadException;
import org.anddev.andengine.entity.scene.Scene;
import org.anddev.andengine.entity.util.FPSLogger;
import org.anddev.andengine.extension.physics.box2d.FixedStepPhysicsWorld;
import org.anddev.andengine.opengl.texture.TextureOptions;
import org.anddev.andengine.ui.activity.BaseGameActivity;
import org.anddev.andengine.util.Debug;

import com.Sony.TemplateGame.Player.Quest;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.ContactImpulse;
import com.badlogic.gdx.physics.box2d.ContactListener;
import com.badlogic.gdx.physics.box2d.Manifold;


/**
 *	Driver class, sebagai class utama
 *	@author sony wirawan
 **/
public class TemplateGameActivity extends BaseGameActivity 
{
	public Player player;
	public GameText gameText;
	public GameItem gameItem;
	public SceneUserData scene_userdata;
	public ObjectUserData item_userdata;
	
	public Vector<Scene> vector_scene = new Vector<Scene>();
	public Vector<Object> vector_item = new Vector<Object>();	
	
	public BoundCamera mBoundChaseCamera;
	public final int CAMERA_WIDTH = 480;
    public final int CAMERA_HEIGHT = 320;
	
    private boolean exit = false;
    private boolean remove_item = false;
    private String destination = "";
    private String map_name = "";
    private String code_scene = "";
    
    private Body itemBody;
	private Scene scene;
	
	public TMXTiledMap mTMXTiledMap;
	public TMXLoader tmxLoader;
	
	
	/**
	 *	Method untuk membuat engine
	 *	@return Engine yang digunakan
	 **/
	
	public Engine onLoadEngine() 
	{	// TODO Auto-generated method stub
		this.mBoundChaseCamera = new BoundCamera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
		return new Engine(new EngineOptions(true, ScreenOrientation.LANDSCAPE, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), this.mBoundChaseCamera));
	}

	
	/**
	 *	Method untuk memuat semua resources yang dibutuhkan
	 **/
	
	public void onLoadResources() 
	{	// TODO Auto-generated method stub
		// register FPS logger to engine
		this.mEngine.registerUpdateHandler(new FPSLogger());

		this.player = new Player(this);
		this.gameText = new GameText(this);
		this.gameItem = new GameItem(this);
		
		// control and player texture
		this.player.loadControlResources();
		this.player.loadPlayerResources();
		this.player.loadControl();
		
		// create map scene
		new GameScene(this, "tmx/scene0.tmx", "scene0");
		new GameScene(this, "tmx/scene1.tmx", "scene1");
		new GameScene(this, "tmx/scene2.tmx", "scene2");
		
		// text texture
		this.gameText.loadResources();
		
		// HUD object
		final HUD hud = new HUD();
		hud.attachChild(this.gameText.mScoreText);
		this.mBoundChaseCamera.setHUD(hud);
	}

	
	/**
	 *	Method untuk memuat scene
	 *	@return scene yang akan dijalankan
	 **/
	
	public Scene onLoadScene()
	{	// TODO Auto-generated method stub
		// load scene 1 for default
		return this.run(1);
	}

	
	
	public void onLoadComplete() 
	{	// TODO Auto-generated method stub
	}

	
	/**
	 *	Method untuk mengambil scene
	 *	@return scene yang akan dijalankan
	 **/
	public Scene run(int i) 
	{	// TODO Auto-generated method stub
		this.scene = this.vector_scene.get(i);
		
		// get the map name of new scene
		this.scene_userdata = (SceneUserData) this.scene.getUserData();
		this.map_name = this.scene_userdata.scene_map;
		
		// try to find the entry point
		try 
		{	this.tmxLoader = new TMXLoader
			(	this,
				this.getEngine().getTextureManager(),
				TextureOptions.BILINEAR_PREMULTIPLYALPHA,
				null
			);
			
			this.mTMXTiledMap = this.tmxLoader.loadFromAsset(this, this.map_name); 
		} 
		catch (final TMXLoadException tmxle) 
		{	Debug.e(tmxle); }
		for(final TMXObjectGroup group: this.mTMXTiledMap.getTMXObjectGroups()) 
		{	if(group.getTMXObjectGroupProperties().containsTMXProperty("point", "true"))
			{
				for(final TMXObject object : group.getTMXObjects())
				{	// set the starting point
					if 
					(	object.getName().equals("start") &&
						object.getTMXObjectProperties().containsTMXProperty(this.code_scene, "true")
					)
					{	// set transformation body to entry point
					 	this.scene_userdata.mPlayerBody.setTransform
					 	(	(object.getX()+16)/32,
					 		(object.getY()+16)/32, 
					 		0
					 	);
					}
				}
			}
		}
		
		// attach player
		this.scene.attachChild(this.player.sprite);
		
		// attach text
		this.gameText.mScoreText.setText("SCORE : " + this.player.player_userdata.player_score);
		this.gameText.mDialogText.setText("normal");
		this.scene.attachChild(this.gameText.mDialogText);
		
		// disable all item for default
		for(int x = 0; x < this.vector_item.size(); x++)
		{	this.itemBody = (Body) this.vector_item.get(x);
			this.item_userdata = (ObjectUserData) this.itemBody.getUserData();
			this.itemBody.setActive(false); 
			this.item_userdata.item_sprite.setVisible(false);
		}
		
		
		if(i == 1)	// scene 1
		{	// current quest is to get badge
			if( this.player.player_userdata.player_quest == Quest.GET_BADGE )
			{	for(int x = 0; x < this.vector_item.size(); x++)
				{	this.itemBody = (Body) this.vector_item.get(x);
					this.item_userdata = (ObjectUserData) this.itemBody.getUserData();
					if(this.item_userdata.item_code.equals("badge"))
					{ 	this.itemBody.setActive(true); 
						this.item_userdata.item_sprite.setVisible(true);
					}
				}
			}
		}
		else if(i == 0)	// scene 0
		{	// current quest is to get box
			if( this.player.player_userdata.player_quest == Quest.GET_BOX )
			{	for(int x = 0; x < this.vector_item.size(); x++)
				{	this.itemBody = (Body) this.vector_item.get(x); 
					this.item_userdata = (ObjectUserData) this.itemBody.getUserData();
					if(this.item_userdata.item_code.equals("box"))
					{ 	this.itemBody.setActive(true); 
						this.item_userdata.item_sprite.setVisible(true);
					}
				}
			}
			
			// current quest is to get face
			else if( this.player.player_userdata.player_quest == Quest.GET_FACE )
			{	for(int x = 0; x < this.vector_item.size(); x++)
				{	this.itemBody = (Body) this.vector_item.get(x); 
					this.item_userdata = (ObjectUserData) this.itemBody.getUserData();
					if(this.item_userdata.item_code.equals("face"))
					{ 	this.itemBody.setActive(true); 
						this.item_userdata.item_sprite.setVisible(true);
					}
				}
			}
		}
		
		return this.scene;
	}
	
	
	/**
	 *	Method untuk contact handling
	 *	@param mPhysicsWorld, implementasi dari physics library yang digunakan
	 *	@author sony wirawan
	 **/
	public void loadContact(FixedStepPhysicsWorld mPhysicsWorld) 
	{	// TODO Auto-generated method stub
		// set contact listener
		mPhysicsWorld.setContactListener(new ContactListener()
		{
			/**
			 *	Ketika kontak dimulai
			 **/
			
			public void beginContact
			( 	com.badlogic.gdx.physics.box2d.Contact contact ) 
				{	// TODO Auto-generated method stub
					// contact conditional
					Body BodyA = contact.getFixtureA().getBody();
					Body BodyB = contact.getFixtureB().getBody();
										
					// player collided with wall
					if(BodyA.getUserData() == null || BodyB.getUserData() == null)
					{	
						gameText.mDialogText.setVisible(true);
						gameText.mDialogText.setText
						( "Collided" );
						return; 
					}
				
					// player collided with item
					else
					{
						item_userdata = (ObjectUserData) BodyB.getUserData();
						
						// player collided with exit point
						if( BodyA.getUserData().equals("player") && item_userdata.item_code.equals("exit"))
						{	
							gameText.mDialogText.setVisible(true);
							gameText.mDialogText.setText
							( "Exit" );
							destination = (String) item_userdata.wrap_destination;
							exit = true;
							return;
						}
						
						// player found box item
						else if( BodyA.getUserData().equals("player") && item_userdata.item_code.equals("box"))
						{	
							gameText.mDialogText.setVisible(true);
							gameText.mDialogText.setText
							( "I got the box.!" );
	
							player.player_userdata.player_score += 10;
							gameText.mScoreText.setText
							( "SCORE : " +  player.player_userdata.player_score);
							
							remove_item = true;
							return;
						}
							
						// player found badge item
						else if( BodyA.getUserData().equals("player") && item_userdata.item_code.equals("badge"))
						{	
							gameText.mDialogText.setVisible(true);
							gameText.mDialogText.setText
							( "I got the Badge.!" );
						
							player.player_userdata.player_score += 100;
							gameText.mScoreText.setText
							( "SCORE : "  + player.player_userdata.player_score);
								
							remove_item = true;
							return;
						}
						
						// player found face item
						else if( BodyA.getUserData().equals("player") && item_userdata.item_code.equals("face"))
						{	
							gameText.mDialogText.setVisible(true);
							gameText.mDialogText.setText
							( "I got the Face.!" );
						
							player.player_userdata.player_score += 1000;
							gameText.mScoreText.setText
							( "SCORE : "  + player.player_userdata.player_score);
							
							remove_item = true;
							return;
						}
					}
				}
			
			
				/**
				 *	Ketika kontak selesai
				 **/
				
				public void endContact
				( com.badlogic.gdx.physics.box2d.Contact contact ) 
				{	// TODO Auto-generated method stub
					gameText.mDialogText.setText
					( "Normal" + "\n" );
					gameText.mDialogText.setVisible(false);
				}

				
				
				public void preSolve
				( com.badlogic.gdx.physics.box2d.Contact contact, Manifold oldManifold ) 
				{	}
				
				
				
				public void postSolve
				( com.badlogic.gdx.physics.box2d.Contact contact, ContactImpulse impulse ) 
				{	}
			}
		);
	}

	
	/**
	 *	Method untuk update handling
	 *	@param mScene, scene yang sedang digunakan
	 *	@param body, body dari player
	 *	@author sony wirawan
	 **/
	public void loadUpdate(final Scene mScene, Body body) 
	{	// TODO Auto-generated method stub
		// set update handler
		mScene.registerUpdateHandler
		(	new IUpdateHandler() 
			{	
				public void reset() {	}
				
				
				public void onUpdate(float pSecondsElapsed) 
				{	// TODO Auto-generated method stub
					// exit
					if(exit)
					{	// detach scene object
						mScene.detachChild(gameText.mScoreText);
						mScene.detachChild(gameText.mDialogText);
						mScene.detachChild(player.sprite);

						// get current code_scene
						scene_userdata = (SceneUserData) mScene.getUserData();
						code_scene = scene_userdata.scene_code;
						
						// select scene
						if(destination.equals("scene0"))
						{	getEngine().setScene(run(0)); }
						else if(destination.equals("scene1"))
						{	getEngine().setScene(run(1)); }
						else if(destination.equals("scene2"))
						{	getEngine().setScene(run(2)); }
						
						exit = false;
					}
					
					// remove item
					if(remove_item)
					{	// which item will be removed
						// remove box item
						if(player.player_userdata.player_quest == Quest.GET_BOX)
						{
							for(int x = 0; x < vector_item.size(); x++)
							{	itemBody = (Body) vector_item.get(x);
								item_userdata = (ObjectUserData) itemBody.getUserData();
								if(item_userdata.item_code.equals("box"))
								{ 	itemBody.setActive(false); 
									item_userdata.item_sprite.setVisible(false);
								}
							}
							
							player.player_userdata.player_quest = Quest.GET_BADGE;
							remove_item = false;
						}
						
						// remove badge item
						else if(player.player_userdata.player_quest == Quest.GET_BADGE)
						{
							for(int x = 0; x < vector_item.size(); x++)
							{	itemBody = (Body) vector_item.get(x);
								item_userdata = (ObjectUserData) itemBody.getUserData();
								if(item_userdata.item_code.equals("badge"))
								{ 	itemBody.setActive(false); 
									item_userdata.item_sprite.setVisible(false);
								}
							}
							
							player.player_userdata.player_quest = Quest.GET_FACE;
							remove_item = false;
						}

						// remove face item
						else if(player.player_userdata.player_quest == Quest.GET_FACE)
						{
							for(int x = 0; x < vector_item.size(); x++)
							{	itemBody = (Body) vector_item.get(x);
								item_userdata = (ObjectUserData) itemBody.getUserData();
								if(item_userdata.item_code.equals("face"))
								{ 	itemBody.setActive(false); 
									item_userdata.item_sprite.setVisible(false);
								}
							}
							
							player.player_userdata.player_quest = Quest.GET_BOX;
							remove_item = false;
						}
					}
					
					// mDialogText always follow the player sprite
					gameText.mDialogText.setPosition
					(	player.sprite.getX(),
						player.sprite.getY()-32 
					);
				}
			}
		);
	}
}